package xm.manager
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.utils.Dictionary;
	
	import spark.events.PopUpEvent;
	
	import xm.core.XMSprite;
	import xm.events.PopupEvent;
	import xm.interfaces.IPopupManager;
	
	/**
	 * <br> 클래스 설명 : </br>
	 * @author 김정환
	 */	
	public class PopupManager implements IPopupManager
	{
		
		private static var _instance : IPopupManager;
		

		/**
		 * @public
		 */
		public static function getInstance():IPopupManager
		{
			if (!_instance)
				_instance = new PopupManager( new singletonEnforce() );
			
			return _instance;
		}
		
		
		//-----------------------------------------------------------------------------------
		// public vars
		//-----------------------------------------------------------------------------------
		
		
		
		
		//-----------------------------------------------------------------------------------
		// protected / internal vars
		//-----------------------------------------------------------------------------------
		
		
		
		
		//-----------------------------------------------------------------------------------
		// private vars
		//-----------------------------------------------------------------------------------
		
		private var _modalWindow : Sprite;
		private var _popupList : Array = [];
		
		
		private var _dicCloseHandler : Dictionary = new Dictionary( true );
		
		//-----------------------------------------------------------------------------------
		// public functions
		//-----------------------------------------------------------------------------------
		
		/**
		 * constructor 
		 */	
		public function PopupManager( se : singletonEnforce )
		{
			if( se == null )
			{
				throw new Error( "싱글턴 객체이므로 생성이 불가합니다." );
			}
			
		}
		
		
		
		/**
		 * 팝업을 생성과 동시에 add 함. 
		 * @param className : XMSprite 상속객체 타입
		 * @param closeHandler : Function
		 * @param modal : 딤처리여부
		 * @return new className() 를 통해 생성된 XMSprite 타입 객체.
		 */		
		public function createPopUp(className:Class, closeHandler : Function = null, modal:Boolean = true):XMSprite
		{
			var sp : XMSprite = new className() as XMSprite;
			addPopUp( sp, closeHandler, modal );
			return sp; 
		}
		
		
		/**
		 * 실제 화면에 popup을 add함.
		 * @param popUp : XMSprite 상속객체
		 * @param closeHandler : Function
		 * @param modal : 딤처리여부
		 */		
		public function addPopUp(popUp:XMSprite, closeHandler : Function = null, modal:Boolean = true, isModalClickToClosePopup : Boolean = true ):void
		{
			var s : Stage = StageManager.getInstance().stage;
			
			_dicCloseHandler[ popUp ] = closeHandler;
			
			if( s != null )
			{
				if( modal && (_modalWindow == null || ( _modalWindow && s.contains( _modalWindow ) == false ) ) ) addModal(isModalClickToClosePopup);
				s.addChild( popUp );
				_popupList.push( popUp );
			}
		}
		
		
		/**
		 * 팝업 중앙정렬.
		 * @param popUp
		 */		
		public function centerPopUp(popUp:XMSprite):void
		{
			var s : Stage = StageManager.getInstance().stage;
			popUp.x = (s.stageWidth-popUp.viewWidth)/2;
			popUp.y = (s.stageHeight-popUp.viewHeight)/2;
		}
		
		
		/**
		 * 팝업 제거.
		 * @param popUp : XMSprite 상속객체 ( 등록되어있는 팝업 )
		 */		
		public function removePopUp(popUp:XMSprite):void
		{
			var s : Stage = StageManager.getInstance().stage,
				idx : int; 
			
			if( _dicCloseHandler[ popUp ] != null ) _dicCloseHandler[ popUp ]();
			delete _dicCloseHandler[ popUp ];
			
			if( s != null )
			{
				if( s.contains( popUp ) ) s.removeChild( popUp );
				
				idx = _popupList.indexOf( popUp ); 
				if( idx > -1 ) _popupList.splice( idx, 1 ); 
			}
			
			
			if( _popupList.length == 0 ) removeModal();
		}
		
		/**
		 * 해당 팝업을 가장 상위로 가져온다.
		 * @param popUp : XMSprite 상속객체 ( 등록되어있는 팝업 )
		 */		
		public function bringToFront(popUp:XMSprite):void
		{
			var s : Stage = StageManager.getInstance().stage;
			if( s.contains( popUp ) )
			{
				s.setChildIndex( popUp, s.numChildren-1 );
			}
		}
		
		/**
		 * 팝업을 전부제거함.
		 */		
		public function removeAllPopup():void
		{
			var pop : XMSprite;
			for each( pop in _popupList )
			{
				if( _dicCloseHandler[ pop ] != null ) _dicCloseHandler[ pop ]();
				delete _dicCloseHandler[ pop ];
				
				removePopUp( pop );
			}
		}
		
		//-----------------------------------------------------------------------------------
		// setter / getter
		//-----------------------------------------------------------------------------------
		
		/**
		 * 팝업 띄울때 생기는 Dimed : Sprite
		 * @param value
		 */		
		public function set modalWindow(value:Sprite):void
		{
			
			var isModalAdded : Boolean = false,
				parent : DisplayObjectContainer;
			if( _modalWindow && _modalWindow.parent )
			{
				isModalAdded = true;
				parent = _modalWindow.parent;
				_modalWindow.parent.removeChild( _modalWindow );
				_modalWindow.removeEventListener(MouseEvent.CLICK, onModalClick );
			}
			
			_modalWindow = value;
			_modalWindow.addEventListener(MouseEvent.CLICK, onModalClick );
			if( isModalAdded ) parent.addChild( _modalWindow );
			
		}
		
		//-----------------------------------------------------------------------------------
		// protected functions
		//-----------------------------------------------------------------------------------
		
		
		
		//-----------------------------------------------------------------------------------
		// internal functions
		//-----------------------------------------------------------------------------------
		
		
		
		
		//-----------------------------------------------------------------------------------
		// private functions
		//-----------------------------------------------------------------------------------
		
		
		// 모달윈도우가 없으면 새로 생성하고,
		// 기본셋팅을 하며, stage 의 Resize 이벤트에 대응한다. 
		// modal이 remove 될때 이벤트 제거.
		private function addModal(isModalClickToClosePopup : Boolean = true):void
		{
			var s : Stage = StageManager.getInstance().stage;
			
			if( _modalWindow == null )
			{
				var g : Graphics;
				_modalWindow = new Sprite();
				g = _modalWindow.graphics;
				g.beginFill( 0x000000, 1 );
				g.drawRect( 0, 0, s.stageWidth,s.stageHeight );
				g.endFill();
				
				_modalWindow.alpha = 0.5;
				
				if( isModalClickToClosePopup ) _modalWindow.addEventListener(MouseEvent.CLICK, onModalClick );
				
			}
			else if( s.contains( _modalWindow ) )
			{
				return;
			}
			
			s.addChild( _modalWindow );
			s.addEventListener(Event.RESIZE, onStageResize );
		}
		
			
		
		// 모달윈도우를 stage에서 제거하고, 리사이즈 이벤트를 제거한다.
		private function removeModal():void
		{
			var s : Stage = StageManager.getInstance().stage;
			if( _modalWindow && s.contains( _modalWindow ) ) s.removeChild( _modalWindow ); 
			s.removeEventListener(Event.RESIZE, onStageResize );
		}
		
		
		//-----------------------------------------------------------------------------------
		// event handler
		//-----------------------------------------------------------------------------------
		
		/**
		 * Dimed 영역이 클릭되면 팝업을 제거한다.
		 * @param e
		 */		
		protected function onModalClick(e:MouseEvent):void
		{
			removeAllPopup();
		}	
		
		/**
		 * @param e
		 */		
		protected function onStageResize(e:Event):void
		{
			var s : Stage = StageManager.getInstance().stage;
			if( _modalWindow && _modalWindow.parent )
			{
				_modalWindow.width = s.stageWidth;
				_modalWindow.height = s.stageHeight;
			}
		}
		
		
		
		
		
		
		
	}
}




class singletonEnforce{}